<template>
  <div>
    <el-upload
      :class="['bl-form-upload', { disabled: disabled }]"
      ref="upload"
      v-bind="$myProps"
      v-on="$myListeners"
      :drag="drag"
      :auto-upload="autoUpload"
      :headers="myHeaders"
      :file-list="myFileList"
      :on-remove="handlerRemove"
      :on-success="handlerSuccess"
      :on-error="handlerError"
      :on-progress="handlerProgress"
      :on-change="handlerChange"
      :on-preview="handlerPreview"
      :before-upload="handlerBeforeUpload"
      :before-remove="handlerBeforeRemove"
      :on-exceed="handlerExceed"
      :http-request="httpRequest"
    >
      <el-button v-if="listType == 'text'" size="small" type="primary"
        >点击上传</el-button
      >
      <i v-else slot="default" class="el-icon-plus"></i>

      <div slot="tip" class="el-upload__tip" v-html="tip"></div>
    </el-upload>

    <el-image
      v-if="listType != 'text'"
      v-show="false"
      ref="dialogImage"
      class="el-upload-list__item-thumbnail el-upload-view"
      :src="dialogImageUrl"
      :z-index="99999999"
      :preview-src-list="imgList"
    ></el-image>
  </div>
</template>



<script>
export default {
  components: {},
  data() {
    return {
      myAction: "/ossApi",
      Folder: this.$store.getters.config.ossFolder,
      imageUrl: this.$store.getters.config.ossImage,
      myFileList: [],
      dialogImageUrl: "",
    };
  },
  watch: {
    value: {
      immediate: true,
      handler(newVal) {
        this.myFileList = newVal || [];
      },
    },
    myFileList: {
      immediate: true,
      handler(newVal) {
        if (this.value != newVal) {
          this.$emit("input", newVal);
        }
      },
    },
  },
  computed: {
    //可预览的图片文件列表
    imgList() {
      console.log(1111);
      let list = this.myFileList
        .filter((file) => this.isPreview({ file }))
        .map((file) => file.url);
      return list;
    },
    // 请求header
    myHeaders() {
      let headers = this.headers || {};
      let token = this.$store.getters.token;

      if (token) {
        headers["Authorization"] = `token ${token}`;
      }

      return headers;
    },
    //继承的属性
    $myProps() {
      let myProps = this.$public.inheritProps(this);
      myProps.action = myProps.action || this.myAction;
      myProps.limit = myProps.limit || this.limit;

      let multiple = true;
      if (myProps.limit == 1) {
        multiple = false;
      }
      myProps.multiple = myProps.multiple || multiple;
      // this.$delete(myProps, "limit");
      // this.$delete(myProps, "action");
      // this.$delete(myProps, "headers");
      this.$delete(myProps, "drag");
      this.$delete(myProps, "autoUpload");
      this.$delete(myProps, "tip");
      // this.$delete(myProps, "multiple");
      // this.$delete(myProps, "list-type");

      this.$delete(myProps, "on-remove");
      this.$delete(myProps, "on-success");
      this.$delete(myProps, "on-error");
      this.$delete(myProps, "on-progress");
      this.$delete(myProps, "on-change");
      this.$delete(myProps, "on-preview");
      this.$delete(myProps, "before-upload");
      this.$delete(myProps, "before-remove");
      this.$delete(myProps, "on-exceed");

      this.$delete(myProps, "primaryKey");
      this.$delete(myProps, "primaryId");
      this.$delete(myProps, "documentKeyName");
      this.$delete(myProps, "documentNavgationName");

      return myProps;
    },
    //继承的事件
    $myListeners() {
      let myListeners = this.$public.inheritListeners(this);

      return myListeners;
    },
  },
  created() {
    if (process.env.NODE_ENV != "development") {
      this.myAction = this.$store.getters.config.ossURL;
    }
  },
  props: {
    value: Array,
    //文件列表的类型
    listType: {
      type: String,
      default: "picture-card",
    },
    headers: {
      type: Object,
      default() {
        return {};
      },
    },
    accept: String,
    tip: String,
    autoUpload: { type: Boolean, default: true },
    drag: { type: Boolean, default: true },
    //限制上传文件个数
    limit: {
      type: Number,
      defaul: 5,
    },
    //限制单文件大小 10m
    limitSize: {
      type: Number,
      default() {
        return 10 * 1024 * 1024;
      },
    },
    disabled: {
      type: Boolean,
      default: false,
    },
  },
  methods: {
    //是否可以直接预览
    isPreview({ file }) {
      console.log(file, 111);
      file = (file && file.raw) || file;

      let type = file.type || "";

      return /^image\//.test(type);
    },
    //上传文件之前的钩子，参数为上传的文件，若返回 false 或者返回 Promise 且被 reject，则停止上传。
    handlerBeforeUpload(file) {
      let flag = true;
      //超出文件上传大小限制
      flag = this.checkFileSize(file);
      if (!flag) {
        return false;
      }

      flag = this.checkFileType(file);
      //文件类型不合法
      return flag;
    },
    //文件列表移除文件时的钩子
    handlerRemove(file, fileList) {
      this.myFileList = fileList;

      this.$emit("on-remove", file, fileList);
    },

    //删除文件之前的钩子，参数为删除的文件和文件列表，若返回 false 或者返回 Promise 且被 reject，则停止删除。
    handlerBeforeRemove(file, fileList) {
      this.myFileList = fileList;
    },
    //文件超出个数限制时的钩子
    handlerExceed(file, fileList) {
      this.$notify.error(`只允许上传[${this.limit}]个文件`);
      this.myFileList = fileList;

      this.$emit("on-exceed", file, fileList);
    },
    // 点击文件列表中已上传的文件时的钩子
    handlerPreview(file) {
      //进行文件下载
      if (this.listType == "text") {
        this.$http.getStream(
          this.myAction + "/OssSelFileStream?FileId=" + file.value,
          ""
        );
      }
      //图片并且是卡片模式
      else if (/^image\//.test(file.type) && this.listType == "picture-card") {
        this.dialogImageUrl = file.url;
        this.$refs.dialogImage.showViewer = true;
      }
    },
    // 自定义上传
    httpRequest(param) {
      if (!this.autoUpload) {
        return;
      }

      var fileObj = param.file;
      var form = new FormData();
      // 文件对象
      form.append("files", fileObj);
      // 文件对象
      form.append("Folder", this.Folder);

      this.$http.post(
        this.myAction + "/OssUpFile/",
        form,
        (res) => {
          if (res.status) {
            param.onSuccess(res);
          } else {
            param.onError(res);
          }
        },
        (error) => {
          param.onError(error);
        }
      );
    },
    // 文件上传成功时的钩子
    handlerSuccess(response, file, fileList) {
      let ents = fileList.filter((c) => c.uid == file.uid);
      if (ents.length == 1) {
        ents[0].value = response.data[0].storageName;
      }
      this.myFileList = fileList;
    },
    // 文件上传失败时的钩子
    handlerError(err, file, fileList) {
      // 从未上传列表中删除文件
      this.$notify.error("文件上传失败，" + err.message);
    },
    // 文件上传时的钩子
    handlerProgress(event, file, fileList) {
      this.myFileList = fileList;
    },
    // 文件状态改变时的钩子，添加文件、上传成功和上传失败时都会被调用
    handlerChange(file, fileList) {
      if (!this.autoUpload) {
        this.myFileList = fileList;
      }
    },

    //检测文件大小是否符合要求
    checkFileSize(file) {
      if (file.size > this.limitSize && this.limitSize > 0) {
        this.$notify.error(`上传文件超出大小限制，不能上传`);
        return false;
      }
      return true;
    },
    //检测文件类型是否复合要求
    checkFileType(file) {
      if (this.accept) {
        let listAccept = this.accept.split(/,/).map((item) => item.trim());

        let type = (file.raw && file.raw.type) || file.type || "";

        if (
          listAccept.indexOf(`.${this.getExtension(file.name)}`) == -1 &&
          !listAccept.some((accept) =>
            type.startsWith(accept.replace(/\*/, ""))
          )
        ) {
          this.$notify.error(`上传文件类型不合法，不能上传`);
          return false;
        }
      }

      return true;
    },
    //获取文件名的后缀名称
    getExtension(fileName) {
      return fileName.replace(/.*\.([^\.][a-z|A-Z|0-9]{2,5})$/g, "$1");
    },
  },
};
</script>

<style>
.el-upload-dragger {
  width: 100% !important;
  height: 100% !important;
}
.el-image__error,
.el-image__inner,
.el-image__placeholder {
  width: 146px !important;
  height: 146px !important;
}
.el-upload-list--picture-card .el-upload-list__item {
  margin: 0 8px 0px 0;
}
.el-upload__tip {
  font-size: 12px;
  color: #606266;
  margin-top: -6px !important;
}
</style>